
#include "GlutTools.h"

#include <vector>
#include <algorithm>
#include <ctime>
#include <fstream>

int generateUniqueNumber()
{
    static std::vector<int> usedNumbers;
    std::vector<int>::iterator it;
    int num;
    srand(static_cast<unsigned int>(time(NULL)));
    while (usedNumbers.end() != (it = std::find(usedNumbers.begin(), usedNumbers.end(), num = rand())));
    usedNumbers.push_back(num);
    return num;
}

/// TextureImage
TextureImage::TextureImage() :
    pRec(new AUX_RGBImageRec)
{
    pRec->data = 0;
}

TextureImage::TextureImage(const char* filename) :
    pRec(new AUX_RGBImageRec)
{
    pRec->data = 0;
    load(filename);
}

TextureImage::~TextureImage()
{
    if (pRec->data)
        free(pRec->data);
}

bool TextureImage::load(const char* filename)
{
    if (pRec->data) {
        free(pRec->data);
        pRec->data = 0;
    }

    std::ifstream file(filename);
    if (file) {
        if (pRec->data) {
            free(pRec->data);
            pRec->data = 0;
        }

        AUX_RGBImageRec* p = 0;
        if (p = auxDIBImageLoadA(filename))
            pRec.reset(auxDIBImageLoadA(filename));
        return reinterpret_cast<bool>(p);
    }
    return false;
}

bool TextureImage::isValid() const
{
    return (0 != pRec->data);
}

int TextureImage::width() const
{
    return (pRec->data) ? pRec->sizeX : 0;
}

int TextureImage::height() const
{
    return (pRec->data) ? pRec->sizeY : 0;
}

const void* TextureImage::data() const
{
    return pRec->data;
}

TextureImage::operator bool() const
{
    return isValid();
}

/// Texture
Texture::Texture(GLenum target)
{
    nTarget = target;
    nId = 0;
}

GLuint Texture::id() const
{
    return nId;
}

GLenum Texture::target() const
{
    return nTarget;
}

void Texture::init(const TextureImage& image, GLint min, GLint mag, GLint level, GLint internalFormat, GLenum  format)
{
    if (nId)
        return;

    glGenTextures(1, &nId);
    glBindTexture(nTarget, nId);
        
    glTexParameteri(nTarget, GL_TEXTURE_MIN_FILTER, min);
    glTexParameteri(nTarget, GL_TEXTURE_MAG_FILTER, mag); 

    glTexImage2D(nTarget, level, internalFormat, image.width(), image.height(), 0, format , GL_UNSIGNED_BYTE, image.data());
}

void Texture::initMipmap(const TextureImage& image, GLint min, GLint mag, GLint internalFormat, GLenum  format)
{
    if (nId)
        return;

    glGenTextures(1, &nId);
    glBindTexture(nTarget, nId);
        
    glTexParameteri(nTarget, GL_TEXTURE_MIN_FILTER, min);
    glTexParameteri(nTarget, GL_TEXTURE_MAG_FILTER, mag);

    gluBuild2DMipmaps(nTarget, internalFormat, image.width(), image.height(), format, GL_UNSIGNED_BYTE, image.data());
}




